Universal OS 1.30 for TI-89 and TI-92 Plus
Copyright (c) 2000-2001. All rights reserved.
Available on www.ticalc.org and www.ti-fr.org
ftp://jm.devel.bourges.net

I) Introduction

Universal OS is a kernel. It works on all calculators and it is 'fully'
(see the 'Features' section) compatible with DoorsOS II 0.99. You can
archive any library and run any program greater than 8 kb on ROM 2.0x
directly. Grayscales work on HW1 and HW2 if the program uses a recent
library to manage them : for example, graphlib, gray4lib or gray7lib
(8-level grayscales aren't supported on HW2).

Universal OS isn't finished, and there are still a few restrictions.

Archive contents:
- install: to install and to uninstall Universal OS
- kernel: the kernel (necessary only for the installation)

Universal OS is freeware. The distribution of Universal OS is
encouraged, as long as all the files are kept together, and unmodified
from the form in which they were originally released.

II) Installing and Using Universal OS

If you have a HW2 2.0x calculator, you must use HW2Patch.

Copy all the files to a folder on the calculator. Launch "install".
Once installed, you can run any assembly program.

To uninstall Universal OS, you must run the install program again (and
it will automatically detect that you want to uninstall). Using the
included install program is the only way that you can uninstall
Universal OS correctly.

NOTES: - The file "kernel" must be in the same folder as "install".
       - Use Universal OS at you own risk and I cannot be held
         responsible for any damage done to your calculator.
       - DON'T INSTALL DoorsOS after installing Universal OS.
       - DON'T UNINSTALL Universal OS with "Doors\uninstal".
       - Universal OS doesn't automatically replace an old kernel for
         reasons of security.

III) Features

- Util, userlib, gray4lib, gray7lib (except on HW2), graphlib and
  linelib have been reprogrammed and integrated (i.e. in the 'kernel'
  variable) into Universal OS.
  ANY EXTERNAL LIBRARY WHICH HAS ONE OF THESE NAMES WILL BE IGNORED.
- You can launch the program called 'doors' with [Shift]+[ON].
  One difference with Doors : [Shift]+[ON] works more often.
- Any reset is detected and a menu is displayed :
  1) reset
  2) turn off
  3) send all the vars to another calc
  Notes :
  - thanks to VTI, you can also send to a computer
  - the calc may not manage to stay off : if it stays off more than two
    seconds, it's ok. I'll try to find a solution.
  - WARNING ! This functionality doesn't guarantee that the sent vars
    don't crash the destination calc. Indeed, they may have been
    modified if there has been a crash. The best would be to save the
    content of the destination calc.
- You can turn off the calculator at any time (even if AMS is busy) by
  pressing [2nd]+[ON].
- You can exit an assembly program at any time by pressing ESC+ON.

- Universal OS doesn't recover memory left unfreed by programs.
  Personally, I don't see how to know if a handle must be freed or not.
  Besides, the algorithm used by DoorsOS isn't perfect.
- The reloc functions aren't supported. For example, prosit won't work.
  (I think prosit is the only one.)
- The userlib::exec function doesn't support zipped programs. This is
  the only difference with the DoorsOS II 0.98 libraries.

IV) Notes For Programmers

These remarks also concern programmers who use DoorsOS.

* ramcalls :

- Idle equ _RAM_CALL_015 :

  void Idle (void); (=> d0-d2/a0-a1 are destroyed)

  Let I be the interrupt mask, Idle returns as soon as an AIn interrupt
  with n > I is triggered. So there is a notable difference with
  tios::idle : whatever I, tios::idle returns if n > 1, unless a key is
  down : in this case, it also returns if n = 1.

  => Whereas this funcion permits to save some more energy, replace 
  tios::idle by Idle stupidly in a program will increase the
  consumption ! In fact, Idle allows userlib/util::idle_loop to be more
  efficient, notably when grayscales are activated.
  To use this function efficiently, I will have to be managed.
  => Idle will never behave exactement like tios::idle (except when
  userlib/util::idle_loop uses it, but it can access to an internal
  flag). tios::idle could still be useful if grayscales aren't
  activated.

  Contrary to tios::idle, Idle runs properly on VTI. It isn't a matter
  of consumption (!) but execution time is now respected.

- Other ramcalls are documented in DoorsOS.

* userlib :

- userlib::KbdMgr equ userlib@0012 :

  In the a0 register, it requires the address of a function, which will
  be called by KbdMgr with a parameter in d0.l :
  - d0.l > 0 : code of the last key pressed 
  - d0.l = 0 : specified time elapsed
  This function must answer through d0.l :
  - d0.l >= 0 : KbdMgr exits with this value
  - d0.l < 0 : ~d0.l (~ = not) spcified a delay in ms (milliseconds)
    The delay is counted from the last call with d0.l = 0, which means
    that if a key is pressed after a waiting for 0.1 s, to return ~1000
    will give the control back 0.9 s later. So the management of the
    keyboard doesn't interfere with the timer. If you really want KbdMgr
    to recall the function 1 s later, you must return ~0 first.
  The APD is supported. Idle is used. KbdMgr est reentrant. In case of
  error, d0.l < 0.

  d1-a6 registers : KbdMgr doesn't destroyed any one, and they are
  passed to the specified function at the call of KbdMgr.

  Like userlib/util::idle_loop, this function rests on the AI1 of tios.
  Besides, idle_loop comes down to this :

  idle_loop:
	move.l	a0,-(a7)
	lea	IdleLoopCallBack(pc),a0
	jsr	KbMgr
	move.l	(a7)+,a0
	rts
  IdleLoopCallBack:
	tst.w	d0
	bne.b	ILCBret
	move.l	#$80000000,d0 ; wait for
  ILCBret:
	rts	;  24j 20h 31min 23.647s :)

  However, there is a difference with the idle_loop routine of
  Universal OS : see notes about Idle.

* The exit point:

Imagine this case: Library X uses library Y in its exit point and Y uses
X in its exit point. If X or Y needs any information it had deleted,
there is a bug, no matter how sophisticated the anti-crash protection
is. My message is that you shouldn't use libraries in your exit point.

* Compatibility:

To prevent problems with new ROM versions, avoid constants. Preferably,
use RAM CALLS and libraries, THEN ROM CALLS. Indeed, TI has changed a
few ROM CALLS on ROM 2.xx : for example, _ROM_CALL_15C doesn't point to 
EM_blockErase, but to a keyboard variable.
Don't use LCD_MEM if the program is in grayscales !  Use the exported
variables.

Be sure that your program is compatible with the TI-89 and the TI-92+.
The concern here is the keyboard.

* The doorsos.h header file:

Don't use:
- doorsos::caddcert		equ	_ROM_CALL_126
  doorsos::cfindcertfield	equ	_ROM_CALL_129
  doorsos::cgetcert		equ	_ROM_CALL_12C
  doorsos::cgetvernum		equ	_ROM_CALL_131
  doorsos::EM_blockErase	equ	_ROM_CALL_15C
  doorsos::EM_blockVerifyErase	equ	_ROM_CALL_15D
  doorsos::EM_delete		equ	_ROM_CALL_15E
  doorsos::EM_open		equ	_ROM_CALL_163
  doorsos::EM_put		equ	_ROM_CALL_164
  doorsos::EM_writeToExtMem	equ	_ROM_CALL_168
- APD_INIT	equ	LCD_MEM+$F10
  APD_TIMER	equ	LCD_MEM+$F14
  APD_FLAG	equ	LCD_MEM+$F42
  but the userlib::get_APD and userlib::get_ADP functions.
- doorsos::ER_throw macro
   dc.w $A000+\1
   endm
  For security, and even if I improved the anti-crash protection, so
  that your program exits more cleanly.

* The ROM functions:

Consider that all ROM functions destroy D0-D2/A0-A1.
This explains why Falldown and Tetris don't save names on ROM 2.xx. So,
be careful with the WriteStr and WriteStrA macros.

V) Known Problems

This kernel uses the supervisor stack and saves some information in it.
The problem is that some buggy programs write in it. With other kernels,
this isn't a problem because they don't save anything in it, but with
Universal OS, the calculator may crash.

On HW2, because of the new method used for grayscales, Universal OS does
not use anymore the auto-int 1, but the auto-int 5, which may cause some
problems that I won't explain since other grayscales libraries (GenLib,
TEOS\graphlib...) use it and grayscales should already work.

VI) To do

- supports the reloc functions
- finish the userlib::exec function so that it can launch zipped
  programs
- prevent the graphical functions from writing out of the selected plane
  if the coordinates are bad and report the bug using a message

VII) History

05/01/2001 : Universal OS 1.30
- Support of C programs which were compiled before the support of exit
  and atexit is corrected.
- Universal OS detects if it is launched on VTI.
- VTI HW2 (note : if the boot code is absent, AMS 2.0x considers that it
  is a HW2, but Universal OS reacts like AMS 1.0x and detects a HW1) :
  - The $70001D port is 'emulated' so that the HW2 grayscales routine
    works.
  - AMS 2.0x : HW2Patch isn't required at the installation.
- The status is redrawn during the restoration of the screen, so that
  this one is synchronized with the changes made by programs.
- Fixed a bug in ReturnValue (_RAM_CALL_00F).
- For the programmers (see IV) :
  - Added the Idle ramcall (see IV) : this function has the same goal as
    tios::idle but it corrects big drawbacks :
    - When grayscales are activated, Idle let AI1 be triggered normally
      to prevent them from blinking.
    - Under VTI, the $600005 port is emule to avoid any error about
      execution times.
  - Added userlib::KbdMgr. In fact, it was already present, but
    undocumented et bugged. 


01/20/2001 : Universal OS 1.21
- HW2 : New grayscales manager, theorically perfect.
  I've given up the Johan Eilert's implementation
  (http://alh.dhs.org/ti89/hw2graypost.html) but I've kept his idea
  (avoiding to refresh the lines which are being displayed, thanks to
  the $70001D port).

01/11/2001 : Universal OS 1.20
- HW2 : Perfect grayscales, no more adjustement needed (in fact, yes !).
  So adjust is removed and the [<>]+[<] or [<>]+[>] commands don't
  have any more effect.
  The method has been found by Johan Eilert. However, I didn't manage
  to implement it exactly as he describes it at
  http://alh.dhs.org/ti89/hw2graypost.html.
  Thanks a lot to Thibaut Giesi and Flavien Racine for having done all
  the tests on 89 and 92+. It took them hours.
- When the calculator is turned off with Universal OS ([2nd]+[ON]), the
  busy indicator is displayed, as with AMS.
  Personally, I find this entirely useless but someone asked me to fix
  this detail.
- Fixed a bug in kernel::exec.

10/15/2000 : Universal OS 1.14
- HW_VERSION ramcall supported.
- Fixed a bug in userlib/util::exec.

05/28/2000 : Universal OS 1.13
- HW2 89&92+ : the adjustment of the grayscales with [<>]+[<] and
  [<>]+[>] should work more often.
- The idle_loop no longer modify the busy flag (it doesn't even clear
  it, contrary to the DoorsOS libraries).

05/25/2000 : Universal OS 1.12
- HW2 89&92+ : adjustment of the grayscales with [<>]+[<] and [<>]+[>]
  (adjust permits to estimate the quality of the grayscales well).
- HW2 : bugfix in graphlib::gray4.
- The use of [Shift]+[ON] no longer disables the basic from an assembly
  program : for example, it was impossible to launch a basic program
  from "doors".

05/11/2000 : Universal OS 1.11
- Grayscale improved on 89 (thanks to Olivier Serres).
- [Shift]+[ON] supported : it launches the 'doors' program.
- Userlib updated : userlib::password added.
- Grayscale routines updated :
  - initialization of the bitplanes.
  - page flipping support in graphlib.
- All problems with return values are solved (there were two bugs : one
  in AMS 2.0x, and another in Universal OS).
- Universal detects if HW2Patch is necessary.
- On HW2 : the uninstallation doesn't reactivates the 8 kb harware limit
  any more if the method which doesn't modify the ROM has been chosen.
- Bugfixes.

02/27/2000 : Universal OS 1.10
- You can save all your data just before a reset.
- [2nd]+[ON] works even if AMS is busy.
- The kernel file can be archived.
- It is possible not to set a password.
- Fixed bugs in:
  - graphlib::clr_scr2 (!)
  - the grayscale routines.
  - kernel::exec

01/08/2000 : Universal OS 1.02
- Libraries can be in any folder.
- Fixed a bug in graphlib::clr_scr2.

01/03/2000 : Universal OS 1.01
- Fixed bugs in:
  - doorsos::kb_globals (_RAM_CALL_010)
  - util::clr_scr
  - userlib::lockcalc
  - checksum of phoenix

01/02/2000 : Universal OS 1.00

VIII) How to contact me

You can e-mail me at: <Julien.Muchembled@netcourrier.com>

Please report any and all bugs you find while using the kernel, and
please don't forget to give me a precise description of what you did and
what happened. However, I have a lot of work so I won't answer if the
problem mentionned is already solved or known, or if I decide to do a
global message in the doc of a future version.